	; This is just a trick to create constants
	.ORIG 2048
ASize:	; Size of the array is 512 elements (2048 bytes) 
	.ORIG 1000
ItNum:	;  Number of sorting iterations
	
	.ORIG 8192
Stack:	; Stack begins at the very top of memory

; System stack will be all addresses below 0x200
	.orig   0x200
SysStackTop:
	; This is our interrupt handler
	.orig	0x200
	addi	re,re,1
	; Save a0,a1,a2 to system stack
	addi    rd,rd,-32
	sw	t0,0(rd)
	sw	t1,4(rd)
	sw	t2,8(rd)
	sw	t3,12(rd)
	sw	a0,16(rd)
	sw	a1,20(rd)
	sw	a2,24(rd)
	sw	a3,28(rd)
	
	xor	t0,t0,t0
	
	rctl	a1,ctl1
	eqi	t1,a1,1
	beqz	t1,NoTimer
	
	; We had a timer interrupt, handle it
	lw	a1,TimerStatus(t0) ;is the sort done running
	bnez a1,DoneDev
	
	; Clear the IP bit in TCTL

	lw	a1,0xf100(t0)
	andi	a2,a1,0x2
	xor	a1,a1,a2
	sw	a1,0xf100(t0)
	
	lw	a1,Hex1(t0)
	addi	a1,a1,1
	sw	a1,Hex1(t0)
	eqi t3,a1,10 
	beqz t3,DispTimer

	;if Hex1 = 10
  	sw  t0,Hex1(t0) ;Hex1 = 0
  	;inc Hex1
 	lw  a1,Hex2(t0) ;a1 = Hex2
 	addi a1,a1,16  	;Hex2++
  	sw  a1,Hex2(t0) ;Store Hex2
  	eqi t3,a1,160    
  	beqz t3,DispTimer
  	;FIRST 2 DIGITS WORK FOR SURE, NEED TO MAKE SURE 3rd AND 4th DO AS WELL

  	;if hex2=10
  	sw  t0,Hex2(t0) ;Hex2 = 0
  	;inc Hex1
 	lw  a1,Hex3(t0) ;a1 = Hex3
 	addi a1,a1,256  ;Hex3++
  	sw  a1,Hex3(t0) ;Store Hex3
  	eqi t3,a1,2560 
  	beqz t3,DispTimer
  	
  	;if hex3=10
  	sw  t0,Hex3(t0) ;Hex3 = 0
  	;inc Hex1
 	lw  a1,Hex4(t0) ;t2 = Hex4
 	addi a1,a1,4096  	;Hex4++
  	sw  a1,Hex4(t0) ;Store Hex4
  	;we limit the count to 4999 as our max
  	eqi t3,a1,20480;
  	beqz t3,DispTimer 
  	sw t0,Hex4(t0)
 	
DispTimer:
  ;display Hex1, Hex2, Hex3, Hex4
	lw  t2,Hex1(t0) ;t2 = Hex1
	add  t3,t2,t0  ;t3 = ToDisplay
	lw  t2,Hex2(t0) ;t2 = Hex2
	add  t3,t3,t2  ;t3 = ToDisplay
	lw  t2,Hex3(t0) ;t2 = Hex3
	add  t3,t3,t2  ;t3 = ToDisplay
	lw  t2,Hex4(t0) ;t2 = Hex3
	add  t3,t3,t2  ;t3 = ToDisplay
	sw t3,0xf800(t0)
	
	

	
	; Increment TestD location
	lw	a1,TestD(t0)
	addi	a1,a1,1
	sw	a1,TestD(t0)
	;  Also display the TestD value in HEX
	;sw	a1,0xf800(t0)
	beq	t0,t0,DoneDev

NoTimer:
	eqi	t1,a1,2
	beqz	t1,DoneDev ;sw interupt for this program does nothing

	; We had a keys interrupt, handle it
	
	; Clear the IP bit in KCTL
	lw	a1,0xf000(t0)
	andi	a2,a1,0x10
	xor	a1,a1,a2
	sw	a1,0xf000(t0)
	;check the status of KEY[0]
	lw	t2,0xf000(t0)
	andi	t2,t2,0x1
	xori	t2,t2,1
	beqz t2,DoneDev
	; Reset everything and return to the start of the program since key[0] is 1
	;xor rc,rc,rc
	xor r0,r0,r0
	xor r1,r1,r1
	xor r2,r2,r2
	xor r3,r3,r3
	xor r4,r4,r4
	xor r5,r5,r5
	xor r6,r6,r6
	xor r7,r7,r7
	xor r8,r8,r8
	xor r9,r9,r9
	xor ra,ra,ra
	xor rb,rb,rb
	xor rc,rc,rc
	xor rd,rd,rd
	xor re,re,re
	xor rf,rf,rf
	addi s0,s0,0x4
	wctl CTL0,s0
	wctl CTL1,t0
	xor S0,S0,S0
	
	;restore Array[0] (value of stack location: 8192)
	
	lw t1,ArrayRestore(t0)
	sw t1,Array(t0)
	
	sw	s0,TimerStatus(s0)
	sw  s0,TestD(s0)
	sw  s0,Hex1(s0)
	sw  s0,Hex2(s0)
	sw  s0,Hex3(s0)
	sw  s0,Hex4(s0)
	xor t1,t1,t1
	sw	t1,0xF100(t1)
	sw	t1,0xF000(t1)
	sw	t1,0xF104(t1)
	beq t1,t1,startof
	;jrl ra,0(rc)
	;reti
	
TestD:
	.word 0xFFFFFFFF
TimerStatus:
	.word 0xFFFFFFFE	
Hex4:
	.word 0xFFFFFFFD
Hex3:
	.word 0xFFFFFFFC
Hex2:
	.word 0xFFFFFFFB
Hex1:
	.word 0xFFFFFFFA
	
DoneDev:
	; Restore register values and return from interrupt
	lw	t0,0(rd)
	lw	t1,4(rd)
	lw	t2,8(rd)
	lw	t3,12(rd)
	lw	a0,16(rd)
	lw	a1,20(rd)
	lw	a2,24(rd)
	lw	a3,28(rd)
	addi	rd,rd,32
	addi	re,re,-1
	reti
	;  Now the actual code
	

	.ORIG 0x400
startof:
	XOR	S0,S0,S0	; Not using GP, we use S0 to hold value zero
	;init on interupts, using t1 to write stuff

	sw	s0,TimerStatus(s0)
	sw  s0,TestD(s0)
	sw  s0,Hex1(s0)
	sw  s0,Hex2(s0)
	sw  s0,Hex3(s0)
	sw  s0,Hex4(s0)

	sw	s0,0xf800(s0)
	
	addi	rd,s0,SysStackTop
	
	;timer
	ori	t1,s0,1000
	sw	t1,0xF104(s0)

	ori	t1,s0,0x5
	sw	t1,0xF100(s0)
	
	;key
	ori	t1,s0,0x20
	sw	t1,0xF000(s0)
	
	addi	t1,s0,0x5
	wctl	ctl0,t1
	ADDI	SP,S0,Stack	; Put SP at top of our memory
	or	re,s0,s0 ;holding interupt nesting level
	; Initialize the array
	ADDI	T0,S0,Array	; T0 = Address of array
	ADDI	T1,S0,ASize
	ADD	T1,T0,T1	; T1 = End of array
	ADDI	T2,S0,1000	; T2 is 1000 
	SUBI	T0,T0,-4	; Array[0] already initialized
Init:
	SW	T2,0(T0)
	ADDI	T2,T2,7
	ADDI	T0,T0,4
	SUB	T3,T0,T1
	LTI	T3,T3,0
	BNEZ	T3,Init
	
	ADDI	T0,S0,ItNum	; Iteration count kept in T0
Loop:
	SUBI	SP,SP,4
	SW	T0,0(SP)	; Save loop counter to stack
	ADDI	A0,S0,Array	; A0 - Address of array
	ADDI	A1,A0,ASize	; A1 - End of array
	ADDI	A2,S0,0		; Sort in ascending order
	JRL	RA,Sort(S0)	; Call Sort
	BEQZ	RV,Error
	ADDI	A0,S0,Array	; A0 - Address of array
	ADDI	A1,A0,ASize	; A1 - End of array
	ADDI	A2,S0,1		; Sort in descending order
	ADDI	T0,S0,Sort
	JRL	RA,0(T0)	; Call Sort
	BEQZ	RV,Error
	LW	T0,0(SP)	; Restore loop counter from stack 
	ADDI	SP,SP,4
	SUBI	T0,T0,1
	SW	T0,0xF804(S0)	; Send counter to LEDR display
	BNEZ	T0,Loop

	ADDI	T0,S0,Array	; T0 = Address of array
	ADDI	T1,T0,ASize	; T1 = End of array
	ADDI	T2,S0,1000	; T2 is 1000
	LW	A0,0(T0)
	ADDI	A1,S0,Stack
	BNE	A0,A1,Error
	ADDI	T0,T0,4
Check:
	BEQ	T1,T0,Done
	SUBI	T1,T1,4
	LW	A0,0(T1)
	BNE	A0,T2,Error
	ADDI	T2,T2,7
	BEQ	T2,T2,Check
Done:
	xori	t1,s0,1
	sw	t1,TimerStatus(s0) ;1- no longer counting
	xor	t1,t1,t1
	sw	t1,0xF100(s0) ;disable timer device
	sw	t1,0xF104(s0)
	ADDI	T0,S0,0xFFFF	; Display FFFF
	SW	T0,0xF804(S0)
	BNEZ	T0,Done		; Loops forever

Error:
	ADDI	T0,S0,0xEEEE	; Display EEEE
	SW	T0,0xF800(S0)
	BNEZ	T0,Error	; Loops forever
	
Sort:	; Sort(beg,end,order)
	; Sorts an array that starts at beg and ends at end
	; If order==0, sorts in ascending order (low to high)
	; If order==1, sorts in descending order (high to low)
	ADDI	T0,A0,0
LoopI:
	BEQ	T0,A1,EndI
	ADDI	T1,T0,4
LoopJ:	
	BEQ	T1,A1,EndJ
	LW	T2,0(T0)
	LW	T3,0(T1)
	BNEZ	A2,Descend
	LT	RV,T2,T3
	BEQ	RV,RV,Decide
Descend:
	LT	RV,T3,T2
Decide:
	BNEZ	RV,NoSwap
Swap:
	SW	T2,0(T1)
	SW	T3,0(T0)
NoSwap:		
	ADDI	T1,T1,4
	BEQ	T1,T1,LoopJ
EndJ:	
	ADDI	T0,T0,4
	BEQ	T0,T0,LoopI
EndI:
	ADDI	RV,RV,1
	JRL	T0,0(RA)
ArrayRestore:  ;used to get the original value back into the Array
	.WORD Stack
Array:
	.WORD Stack
